package com.lihua.project.taskcenter.core.match.impl;


import com.lihua.project.taskcenter.core.match.ITaskMatchRule;
import com.lihua.project.taskcenter.core.utils.TaskListUtils;
import com.lihua.project.taskcenter.core.utils.TaskTagUtils;
import com.lihua.project.taskcenter.taskcenter.domain.Task;
import com.lihua.project.taskcenter.taskcenter.domain.TaskGroup;
import com.lihua.project.taskcenter.taskcenter.service.ITaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * @author lihua
 * @date 2022/3/18 15:27
 * 默认任务匹配规则 TODO 需要优化：更换匹配时，需要将对方加入一个队列，防止马上又匹配成功
 */
@Component("DefaultTaskMatchRule")
@Slf4j
public class DefaultTaskMatchRule implements ITaskMatchRule {

    /**
     * 匹配耗时，最大分数。当匹配耗时大于10小时，那么会给这个任务加10分，防止一直匹配不成功
     * 1小时=1分
     */
    private static final int TIME_SCORE = 10;

    @Autowired
    private ITaskService taskService;

    @Override
    public void matching(List<Task> tasks) {
        Map<Task, Map<Task, Integer>> tasksScore = getTasksScore(tasks);
        List<TaskGroup> tasksScoreSum = getTasksScoreSum(tasksScore);
        //用来存放已经绑定的任务
        HashSet<Task> bindTask = new HashSet<>();
        //绑定任务,选择策略。当任务组的总分大于15，然后依据分数从高到低进行匹配
        Iterator<TaskGroup> iterator = tasksScoreSum.iterator();
        while (iterator.hasNext()) {
            TaskGroup taskGroup = iterator.next();
            if (taskGroup.getScore() > 15) {
                //判断任务组中的任务是否已经被绑定
                if (!bindTask.contains(taskGroup.getTask())&&!bindTask.contains(taskGroup.getTaskLink())){
                    //1、进行绑定，如果绑定成功，进行下面的操作（绑定逻辑，修改数据库中的status状态，修改为匹配成功，也就是 status=2）
                    taskGroup.getTask().setStatus("2");
                    taskGroup.getTask().setTaskLinkId(taskGroup.getTaskLink().getId());
                    int tag = taskService.updateTaskStatusAndTaskLinkId(taskGroup.getTask());

                    taskGroup.getTaskLink().setStatus("2");
                    taskGroup.getTaskLink().setTaskLinkId(taskGroup.getTask().getId());
                    int tag1 = taskService.updateTaskStatusAndTaskLinkId(taskGroup.getTaskLink());

                    if (tag==1&&tag1==1){
                        //2、将任务放入绑定列表
                        bindTask.add(taskGroup.getTask());
                        bindTask.add(taskGroup.getTaskLink());
                        //3、从匹配队列中移除任务
                        TaskListUtils.deleteTasksByTasksId(taskGroup.getTask().getId());
                        TaskListUtils.deleteTasksByTasksId(taskGroup.getTaskLink().getId());
                        log.debug("匹配成功:taskId={} taskTitle={} tag = {} || taskLinkId={} taskLinkTitle={} tagLink = {}",taskGroup.getTask().getId(),taskGroup.getTask().getTaskTitle(),taskGroup.getTask().getTag(),taskGroup.getTaskLink().getId(),taskGroup.getTaskLink().getTaskTitle(),taskGroup.getTaskLink().getTag());
                    }
                }
            }
        }
    }

    /**
     * 获取根据标签和任务匹配消耗时间，给任务打上分数。分数越高权值越高
     * 如果分数低于10，表示没有标签没有匹配成功，
     */
    private Map<Task, Map<Task, Integer>> getTasksScore(List<Task> tasks) {
        Map<Task, Map<Task, Integer>> tasksMapMap = new HashMap<>();
        for (Task task : tasks) {
            for (Task task1 : tasks) {
                //TODO 排除任务和自己发布的其他任务 &&!task.getUserId().equals(task1.getUserId())
                if (!task.getId().equals(task1.getId())&&!task.getUserId().equals(task1.getUserId())) {
                    int score = 0;
                    Set<String> tag1 = TaskTagUtils.getTags(task.getTag());
                    Set<String> tag2 = TaskTagUtils.getTags(task1.getTag());
                    //根据标签计分，有相同的标签加10分
                    for (String s : tag1) {
                        for (String s1 : tag2) {
                            if (s.equalsIgnoreCase(s1)) {
                                score = score + 10;
                            }
                        }
                    }
                    //根据匹配耗时计分
                    long createTime = task1.getCreateTime().getTime();
                    long nowTime = System.currentTimeMillis();
                    long time = (nowTime - createTime) / (1000 * 60 * 60) > 0 ? (nowTime - createTime) / (1000 * 60 * 60) : 0;
                    long timeScore = time > TIME_SCORE ? TIME_SCORE : time;

                    //每匹配耗时一小时，加一分
                    score = score + (int) timeScore;
                    if (tasksMapMap.get(task) == null) {
                        Map<Task, Integer> taskHashMap = new HashMap<>();
                        tasksMapMap.put(task, taskHashMap);
                    }
                    tasksMapMap.get(task).put(task1, score);
                }
            }
        }
        return tasksMapMap;
    }


    /**
     * 获取两个任务的评分和，比如A、B的评分+B、A的评分，得到两个任务的评分和
     */
    private List<TaskGroup> getTasksScoreSum(Map<Task, Map<Task, Integer>> taskMapMap) {

        Set<Task> tag = new HashSet<>();

        List<TaskGroup> taskScoreSum = new ArrayList<>();
        //1、获取每组的权值和
        taskMapMap.forEach((taskA, taskIntegerMap) -> {
            taskIntegerMap.forEach((taskB, score) -> {
                if (!tag.contains(taskB)) {
                    //对于a-b组，a-b的评分
                    int scoreAB = score;
                    //b-a的评分
                    int scoreBA = taskMapMap.get(taskB).get(taskA);
                    //计算a-b组的评分和
                    TaskGroup taskGroup = new TaskGroup(taskA, taskB, scoreAB + scoreBA);
                    taskScoreSum.add(taskGroup);
                }
            });
            //标记已经计算过的任务，防止重复计算
            tag.add(taskA);
        });
        //2、将任务组按照评分进行排序
        Collections.sort(taskScoreSum);
        return taskScoreSum;
    }


    public static void main(String[] args) {

    }
}
